
package com.zed.api.persistence.core.util;

import com.zed.api.persistence.core.VariableReplacer;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * {@link MapVariableReplacer},简单的变量替换器
 *
 * @author Zed
 */
public final class MapVariableReplacer implements VariableReplacer {

    protected static final String EMPTY = "";

    private Map<String, String> variableMap;
    private final Pattern pattern;

    /**
     * 构建方法
     */
    public MapVariableReplacer(Map<String, String> variables) {
        this.variableMap = new HashMap<>(Objects.requireNonNull(variables, "\"variables\" cannot be null."));
        if (variables.isEmpty()) {
            this.pattern = null;
        } else {
            this.pattern = this.buildPattern();
        }

    }

    @Override
    public String findAndReplace(String text) {
        if (text == null)
            return null;
        if (text.length() < 4)
            return text;

        Pattern pattern = this.pattern;
        if (pattern == null)
            return text;

        Matcher matcher = pattern.matcher(text);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, this.variableMap.get(matcher.group(1)));
        }
        matcher.appendTail(sb);

        return sb.length() == 0 ? text : sb.toString();

    }

    /**
     * 构建变量替换的模式
     */
    protected Pattern buildPattern() {
        String patternString = "\\$\\{(" + join(this.variableMap.keySet().iterator(), "|") + ")\\}";
        return Pattern.compile(patternString);
    }

    /**
     * 迭代连接
     *
     * @param iterator  {@link Iterator},迭代器
     * @param separator {@link String},分隔符
     * @return {@link String} {@link String},处理过后的字符串
     */
    private String join(final Iterator<?> iterator, final String separator) {

        // handle null, zero and one elements before building a buffer
        if (iterator == null) {
            return null;
        }
        if (!iterator.hasNext()) {
            return EMPTY;
        }
        final Object first = iterator.next();
        if (!iterator.hasNext()) {
            return Objects.toString(first, "");
        }

        // two or more elements
        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
        if (first != null) {
            buf.append(first);
        }

        while (iterator.hasNext()) {
            if (separator != null) {
                buf.append(separator);
            }
            final Object obj = iterator.next();
            if (obj != null) {
                buf.append(obj);
            }
        }
        return buf.toString();
    }

}
